/*  yALB - Yet Another List Builder (roster Editor for Wargames/tabletop games).
    Copyright (C) 2008-2012  Daniel Ricardo Castro Alvarado

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/

#include "collection.h"

#include <QMessageBox>
#include <QApplication>
#include "other/gameStructs.h"
#include "other/unit.h"

template <class T>
ErrorHandler* Collection<T>::setErrorHandler(ErrorHandler *newHandler) {
    ErrorHandler* oldHandler = errorHandler;
    errorHandler = newHandler;
    return oldHandler;
}

template <class T>
void Collection<T>::addElement(const T &element, const QString &key) {
    if(GameStructs::isValidKey(key)) {
        if(!internalCollection.contains(key)) {
            internalCollection.insert(key, element);
            emit elementAdded(key);
            emit modified();
        } else {
            if(showMessages) {
                QMessageBox::critical(0, QCoreApplication::tr("Can not add this element"),
                                      QCoreApplication::tr("This element can not be added because its ID (%1) already exists").arg(key));
            }
            if(errorHandler) {
                errorHandler->addError(QCoreApplication::tr("Can't add %1: ID already exists").arg(key));
            }
        }
    }
}

template <class T>
void Collection<T>::updateElement(const QString &currentKey, const T &newElement,
                        const QString &newKey) {
    if(internalCollection.contains(currentKey)) {
        if(currentKey != newKey) {
            if(GameStructs::isValidKey(newKey)) {
                if(!internalCollection.contains(newKey)) {
                    internalCollection.insert(newKey, newElement);
                    internalCollection.remove(currentKey);
                    emit elementUpdated(currentKey, newKey);
                    emit modified();
                } else {
                    if(showMessages) {
                        QMessageBox::critical(0, QCoreApplication::tr("Can not update this element"),
                                              QCoreApplication::tr("This element can not be updated because its new ID already exists"));
                    }
                    if(errorHandler) {
                        errorHandler->addError(QCoreApplication::tr("Can't update %1: New ID already exists").arg(currentKey));
                    }
                }
            }
        } else {
            internalCollection.insert(currentKey, newElement);
            emit elementUpdated(currentKey, currentKey);
            emit modified();
        }
    } else {
        if(showMessages) {
            QMessageBox::critical(0, QCoreApplication::tr("Can not update this element"), QCoreApplication::tr("This element can not be updated because it does not exist"));
        }
        if(errorHandler) {
            errorHandler->addError(QCoreApplication::tr("Can't update %1: ID does not exists").arg(currentKey));
        }
    }
}

template <class T>
void Collection<T>::removeElement(const QString &key) {
    if(internalCollection.contains(key)) {
        internalCollection.remove(key);
        emit elementRemoved(key);
        emit modified();
    }
}

template <class T>
QString Collection<T>::cloneKey(const QString &key) {
    T &oldItem = *(getRealElement(key));
    T newItem(oldItem);

    QString newKey;

    int i = 0;
    bool valid = false;

    do {

        newKey = QString("%1_%2").arg(key, QString::number(i));
        if(!GameStructs::isValidKey(newKey)) // Prevent the app to fall in an infinite loop
            break;
        valid = !contains(newKey);
        ++i;
    } while (!valid);

    if(valid) {
        newItem.setName(QString("%1_%2").arg(oldItem.getName(), QString::number(i)));
        addElement(newItem, newKey);
        return newKey;
    }
    return QString();
}

template <class T>
void Collection<T>::clearAll() {
    QStringList keys(internalCollection.keys());
    for(int i = 0; i<keys.size(); ++i)
        internalCollection.remove(keys.at(i));
    emit cleared();
    emit modified();
}

// Prevent linker errors

template class Collection<GameCategory>;
template class Collection<Column>;
template class Collection<GlobalText>;
template class Collection<GameItem>;
template class Collection<UnitOption>;
template class Collection<Unit>;
template class Collection<GameProperty>;
